package com.example.qxfw.csnl.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dmgis.entity.*;
import com.example.qxfw.common.entity.zy.BaseProduct;
import com.example.qxfw.common.entity.zy.WaterLoggingFcst;
import com.example.qxfw.common.service.impl.FileRequestService;
import com.example.qxfw.mongodb.hy.entity.HyDocFile;
import com.example.qxfw.shfx.dto.ColorAndNameDto;
import com.example.qxfw.shfx.entity.ColorAndPos;
import com.example.qxfw.csnl.mapper.WaterLoggingFcstMapper;
import com.example.qxfw.csnl.service.NlybService;
import com.example.qxfw.ybzz.mapper.BaseProductMapper;
import com.example.qxfw.yjqx.dto.LayerRcoDto;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.example.qxfw.common.util.DateUtil.dataToUpper;
import static com.example.qxfw.common.util.DmgisUtils.getColorAndNameMap;
import static com.example.qxfw.common.util.DmgisUtils.getCountryMap;
import static com.example.qxfw.common.util.DocxUtil.*;
import static com.example.qxfw.common.util.DocxUtil.setCellLocation;
import static com.example.qxfw.common.util.LayerUtil.getLayerClass;

@Service
public class NlybServiceImpl implements NlybService {

    @Value("${dmgis.ip}")
    private String dmgisIp;

    @Value("${dmgis.port}")
    private String dmgisPort;

    @Value("${dmgis.serName}")
    private String dmgisSerName;

    @Value("${city}")
    private String city;

    @Value("${filePath.resourcePath}")
    private String resourcePath;

    @Value("${filePath.active}")
    private String active;

    @Autowired
    private WaterLoggingFcstMapper waterLoggingFcstMapper;

    @Autowired
    private BaseProductMapper baseProductMapper;


    @Qualifier("mongoSecondTemplate")
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    FileRequestService ms ;

    @Override
    public Integer getMaxId() {
        List<WaterLoggingFcst> waterLoggingFcsts = waterLoggingFcstMapper.selectList(Wrappers.<WaterLoggingFcst>lambdaQuery()
                .orderByDesc(WaterLoggingFcst::getId)
                .last("limit 1"));
        if (waterLoggingFcsts.size() > 0) {
            return waterLoggingFcsts.get(0).getId();
        } else {
            return 0;
        }
    }

    @Override
    public Object createProduct(Integer issueNum, String userName, String yjType, String sXType, String date, String timeChar, Integer nTimes, String colorAndPos, String posStr, MultipartFile[] images, String layerName, String dlData) throws UnsupportedEncodingException, FileNotFoundException, ParseException {
        //模板路径
        String templatePath;
        //产品路径
        String targetPath;
        //pdf路径
        String targetPdfPath = null;
        //配置文件路径
        String configFilePath;

        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        if (active.equals("dev")) {
            templatePath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\Documents\\城市内涝预报模板\\城市内涝预报模板.docx";
            targetPath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\temp\\城市内涝预报文档.docx";
            targetPdfPath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\temp\\城市内涝预报文档.pdf";
        } else {
            templatePath = applicationHome.getSource().getParentFile() +
                    "\\resource\\Documents\\城市内涝预报模板\\城市内涝预报模板.docx";
            targetPath = applicationHome.getSource().getParentFile() +
                    "\\resources\\temp\\城市内涝预报文档.docx";
        }

        List<DmObj> map = new ArrayList<>();
        Map<Integer, List<ColorAndNameDto>> colorAndNameMap = new HashMap<>();
        //json字符串转换为对象列表
        List<ColorAndPos> posList = JSON.parseArray(colorAndPos, ColorAndPos.class);
        //获取预警区内乡镇数据
        for (ColorAndPos typeAndPos : posList) {
            String type = typeAndPos.getColor();
            String color = "";
            switch (type) {
                case "0":
                    color = "蓝色";
                    break;
                case "1":
                    color = "绿色";
                    break;
                case "2":
                    color = "黄色";
                    break;
                case "3":
                    color = "橙色";
                    break;
                case "4":
                    color = "红色";
                    break;
            }
            //多边形查询乡界面
             map = getCountryMap(dmgisIp,dmgisPort,dmgisSerName,typeAndPos.getPos());


            for (DmObj obj : map) {
                List<DmRcoVal> rec = obj.getRec();
                for (DmRcoVal dmRcoVal : rec) {
                    String fldName = dmRcoVal.getFldName();
                    if (fldName.toLowerCase().equals("name")) {
                        ColorAndNameDto colorAndNameDto = new ColorAndNameDto();
                        colorAndNameDto.setCounty("凌云");
                        colorAndNameDto.setCountry(dmRcoVal.getFldVal());
                        colorAndNameDto.setType(Integer.parseInt(type));
                        colorAndNameDto.setColor(color);
                        List<ColorAndNameDto> colorAndNameDtoList = null;
                        if (colorAndNameMap.containsKey(Integer.parseInt(type))) {
                            colorAndNameDtoList = colorAndNameMap.get(Integer.parseInt(type));
                        } else {
                            colorAndNameDtoList = new ArrayList<>();
                        }
                        colorAndNameDtoList.add(colorAndNameDto);
                        List<ColorAndNameDto> collect = colorAndNameDtoList.stream().distinct().collect(Collectors.toList());
                        colorAndNameMap.put(Integer.parseInt(type), collect);
                    }
                }
            }
        }

            //一级区县内容
            StringBuilder country1 = new StringBuilder();
            //二级区县内容
            StringBuilder country2 = new StringBuilder();
            //三级区县内容
            StringBuilder country3 = new StringBuilder();

            List<ColorAndNameDto> colorAndNameDtoListAll = new ArrayList<>();
            if (colorAndNameMap.containsKey(2)) {
                List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(2);
                colorAndNameDtoListAll.addAll(colorAndNameDtoList);
                for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                    country1.append(colorAndNameDto.getCountry()).append(",");
                }
                country1.deleteCharAt(country1.length() - 1);
            }
            if (colorAndNameMap.containsKey(3)) {
                List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(3);
                colorAndNameDtoListAll.addAll(colorAndNameDtoList);
                for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                    country2.append(colorAndNameDto.getCountry()).append(",");
                }
                country2.deleteCharAt(country2.length() - 1);

            }
            if (colorAndNameMap.containsKey(4)) {
                List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(4);
                colorAndNameDtoListAll.addAll(colorAndNameDtoList);
                for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                    country3.append(colorAndNameDto.getCountry()).append(",");
                }
                country3.deleteCharAt(country3.length() - 1);
            }
            //替换正文内容
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日HH时");
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日");
            SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            Date date1 = sdf.parse(date);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date1);
            //年号
            Integer year = calendar.get(Calendar.YEAR);
            //预报时间
            String ybTime = sdf3.format(date1) + timeChar + "时";
            //当前时间
            String makeTime = sdf1.format(new Date());
            //中文时间
            String upperTime = dataToUpper(sdf2.format(new Date()));

            String warnResult = "";
            if (country1.length() != 0) {
                warnResult += country1;
            }
            if (country2.length() != 0) {
                if (warnResult.length() != 0) {
                    warnResult += "," + country2;
                } else {
                    warnResult += country2;
                }
            }
            if (country3.length() != 0) {
                if (warnResult.length() != 0) {
                    warnResult += "," + country3;
                } else {
                    warnResult += country3;
                }
            }
            //设置分析区域点集和区县内容
            WaterLoggingFcst waterLoggingFcst = new WaterLoggingFcst();
            waterLoggingFcst.setWarnpos(posStr);
            waterLoggingFcst.setWarnarea(warnResult);
            waterLoggingFcst.setWarnResult(warnResult);
            //解析地理分析数据
            List<Object> layerObjectList = new ArrayList<>();
            if (StringUtils.isNotBlank(dlData) && StringUtils.isNotBlank(layerName)) {
                try {
                    List<LayerRcoDto> LayerRcoDtoList = JSON.parseArray(dlData, LayerRcoDto.class);
                    Class layerClass = getLayerClass(layerName);
                    for (LayerRcoDto layerRcoDto : LayerRcoDtoList) {
                        JSONObject rcoValObject = (JSONObject) layerRcoDto.getRcoValObject();
                        Object javaObject = JSON.toJavaObject(rcoValObject, layerClass);
                        layerObjectList.add(javaObject);
                    }
                } catch (Exception e) {
                    System.err.println("地理分析数据解析错误");
                }
            }

            //生成文档
            try (
                    InputStream templateInputStream = new FileInputStream(templatePath);
                    OutputStream targetOutputStream = new FileOutputStream(targetPath);
                    XWPFDocument document = new XWPFDocument(templateInputStream);
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    ByteArrayOutputStream byteArrayOutputStream1 = new ByteArrayOutputStream();
                    ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream()

            ) {
                List<XWPFParagraph> paragraphs = document.getParagraphs();
                //段落替换
                String[] placeholders = new String[]{"[年]", "[文件号]", "[制作人]", "[时间1]", "[时间2]", "[影响区域]", "[中文时间]"};
                //替换内容
                String[] replacements = new String[]{String.valueOf(year), "第" + issueNum + "期", userName, makeTime, ybTime, warnResult, upperTime};

                for (int i = 0; i < paragraphs.size(); i++) {
                    XWPFParagraph paragraph = paragraphs.get(i);
                    String text = paragraph.getText();

                    replaceTextInParagraph(paragraph, placeholders, replacements);

                    //插入图片
                    if (StringUtils.isNotBlank(text) && text.contains("[图1]")) {
                        //获取下标
                        XmlCursor cursor = paragraph.getCTP().newCursor();
                        XWPFParagraph newPara = document.insertNewParagraph(cursor);
                        newPara.setAlignment(ParagraphAlignment.CENTER);//居中
                        XWPFRun newParaRun = newPara.createRun();
                        for (MultipartFile image : images) {
                            //插入图片
                            newParaRun.addPicture(image.getInputStream(), XWPFDocument.PICTURE_TYPE_PNG, "image.png,", Units.toEMU(450), Units.toEMU(406));
                        }
                        document.removeBodyElement(document.getPosOfParagraph(paragraph));
                    }

                    //插入地理分析数据表格
                    if (layerObjectList.size() > 0 && StringUtils.isNotBlank(text) && text.contains("[分析数据]")) {
                        System.out.println("插入地理分析表格数据");
                        //获取下标
                        XmlCursor cursor = paragraph.getCTP().newCursor();
                        XWPFTable table = document.insertNewTbl(cursor);
                        //插入图层表格数据
                        insertTablaLayerData(layerName, layerObjectList, table);
                        setTableLocation(table, "center");
                        setCellLocation(table, "CENTER", "center");
                        document.removeBodyElement(document.getPosOfParagraph(paragraph));

                    }
                }
                // 将生成的文档保存到输出文件
                document.write(targetOutputStream);

                //获取文档名称

                String productName = sdf1.format(date1) + "第" + issueNum + "期城市内涝预警文档.docx";//插入城市内涝预报表数据
                waterLoggingFcst.setMaker(userName);
                waterLoggingFcst.setMaketime(new Timestamp(new Date().getTime()));
                waterLoggingFcst.setDocpath(productName);
                waterLoggingFcst.setForecasttime(Timestamp.valueOf(sdf2.format(date1)+" "+timeChar+":00:00"));
                waterLoggingFcst.setRaintype(sXType);
                waterLoggingFcstMapper.insert(waterLoggingFcst);
                //保存基本产品表数据
                BaseProduct baseProduct = new BaseProduct();
                baseProduct.setProductname(productName);
                baseProduct.setProducttype(yjType+sXType);
                baseProduct.setForecasttime(date1);
                baseProduct.setMaketime(new Date());
                baseProduct.setBindid(waterLoggingFcst.getId());
                baseProduct.setMaker(userName);
                baseProductMapper.insert(baseProduct);
                byte[] buffer = new byte[1024];
                int bytesRead;
                FileInputStream inputStream = new FileInputStream(targetPath);
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    byteArrayOutputStream.write(buffer, 0, bytesRead);
                }
                byte[] byteArray = byteArrayOutputStream.toByteArray();

                wordToPdf(targetPath, targetPdfPath);
             /*   //保存到mongodb库中
                HyDocFile hyDocFile = new HyDocFile();
                hyDocFile.setData(byteArray);
                hyDocFile.setTable_name("base_product");
                hyDocFile.setId(String.valueOf(baseProduct.getId()));
                mongoTemplate.save(hyDocFile);*/


                //保存到mongodb库中
                // HyDocFile hyDocFile = new HyDocFile();
                // hyDocFile.setData(byteArray);
                // hyDocFile.setTable_name("base_product");
                // hyDocFile.setId(String.valueOf(baseProduct.getId()));
                //mongoTemplate.save(hyDocFile);
                Map<String, Object> map1 = new HashMap<String, Object>();
                map1.put("id", baseProduct.getId());
                map1.put("data", byteArray);
                map1.put("table_name", "base_product");
                map1.put("collectionName", "doc_file");
                ms.insertData(map1);


                //pdf入库
                byte[] buffer1 = new byte[1024];
                int bytesRead1 ;
                FileInputStream inputStream1 = new FileInputStream(targetPdfPath);
                while ((bytesRead1 = inputStream1.read(buffer1)) != -1) {
                    byteArrayOutputStream1.write(buffer1, 0, bytesRead1);
                }

                byte[] bytes = byteArrayOutputStream1.toByteArray();
                Map<String, Object> map2 = new HashMap<String, Object>();
                map2.put("id", baseProduct.getId());
                map2.put("data", bytes);
                map2.put("table_name", "base_product");
                map2.put("collectionName", "pdf_file");
                map2.put("advCode", "451027");
                ms.insertData(map2);
                //图片
                for (MultipartFile image : images) {
                    //插入图片
                    InputStream inputStream2 = image.getInputStream();
                    byte[] buffer2 = new byte[1024];
                    int bytesRead2;
                    while ((bytesRead2 = inputStream2.read(buffer2)) != -1) {
                        byteArrayOutputStream2.write(buffer2, 0, bytesRead2);
                    }
                    byte[] bytes2 = byteArrayOutputStream2.toByteArray();
                    Map<String, Object> map3 = new HashMap<String, Object>();
                    map3.put("id", String.valueOf(baseProduct.getId()));
                    map3.put("data", bytes2);
                    map3.put("table_name", "base_product");
                    map3.put("collectionName", "image_file");
                    map3.put("advCode", "451027");
                    ms.insertData(map3);
                }



                // 设置前端响应
                HttpHeaders headers = new HttpHeaders();
                String fileName = "城市内涝等级预报文档.docx";
                headers.setContentDispositionFormData("attachment", new String(fileName.getBytes("UTF-8"),"ISO-8859-1"));
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                headers.setContentLength(byteArray.length);
//            wordToPdf(targetPath,targetPdfPath);
                return new ResponseEntity<>(byteArray, headers, HttpStatus.OK);
            } catch (Exception e) {
                e.printStackTrace();
                System.err.println("文档生成失败");
            }

        return null;
    }
}
